#include <iostream>
#include "../common/Dispatcher.hpp"
#include "../server/RpcRouter.hpp"


void Add(const Json::Value& req, Json::Value& rsp)
{
    int num1 = req["num1"].asInt();
    int num2 = req["num2"].asInt();
    rsp = num1 + num2;
}

int main()
{
    // std::cout << "main begin" << std::endl;

    std::shared_ptr<rpc::Dispatcher> dispatcher = std::make_shared<rpc::Dispatcher>();
    std::shared_ptr<rpc::server::RpcRouter> rpc_router = std::make_shared<rpc::server::RpcRouter>();

    auto callback = std::bind(&rpc::server::RpcRouter::onRpcRequest, rpc_router.get(), 
        std::placeholders::_1, std::placeholders::_2);
    dispatcher->registerHandler<rpc::RpcRequest>(rpc::MSG_TYPE::REQ_RPC, callback);

    std::unique_ptr<rpc::server::ServerDescribeFactory> desc_factory(new rpc::server::ServerDescribeFactory());
    desc_factory->setMethod("Add");
    desc_factory->setParamDesc("num1", rpc::server::ValueType::INTEGRAL);
    desc_factory->setParamDesc("num2", rpc::server::ValueType::INTEGRAL);
    desc_factory->setReturnType(rpc::server::ValueType::INTEGRAL);

    // using ServerCallback = std::function<void(const Json::Value &, Json::Value &)>;
    desc_factory->setCallback(Add);
    
    rpc_router->registerService(desc_factory->build());

    rpc::BaseServer::ptr server = rpc::ServerFactory::create(8080);
    auto message_callback = std::bind(&rpc::Dispatcher::onMessage, dispatcher.get(), 
        std::placeholders::_1, std::placeholders::_2);
    server->setMessageCallback(message_callback);
    server->start();

    return 0;
}

// void onRpcRequest(const rpc::BaseConnection::ptr & conn, const rpc::RpcRequest::ptr &msg)
// {
//     std::cout << "onRpcRequest" << std::endl;
//     std::string body = msg->serialize();
//     std::cout << body << std::endl;

//     rpc::RpcResponse::ptr rsp = rpc::MessageFactory::create<rpc::RpcResponse>();
//     std::string uid = msg->id();
//     rsp->setId(uid);
//     rsp->setMsgType(rpc::MSG_TYPE::RSP_RPC);
//     rsp->setRcode(rpc::RCODE::RCODE_OK);
//     rsp->setResult(33);



//     // std::cout << "already send to client" << std::endl;
//     conn->send(rsp);
//     std::cout << "send success" << std::endl;
// }

// void onTopicRequest(const rpc::BaseConnection::ptr & conn, const rpc::TopicRequest::ptr &msg)
// {
//     std::cout << "onTopicRequest" << std::endl;
//     std::string body = msg->serialize();
//     std::cout << body << std::endl;

//     rpc::RpcResponse::ptr rsp = rpc::MessageFactory::create<rpc::RpcResponse>();
//     std::string uid = msg->id();
//     rsp->setId(uid);
//     rsp->setMsgType(rpc::MSG_TYPE::RSP_RPC);
//     rsp->setRcode(rpc::RCODE::RCODE_OK);
//     rsp->setResult(33);



//     // std::cout << "already send to client" << std::endl;
//     conn->send(rsp);
//     std::cout << "send success" << std::endl;
// }

// int main()
// {
//     rpc::Dispatcher::ptr dispatcher = std::make_shared<rpc::Dispatcher>();
//     dispatcher->registerHandler<rpc::RpcRequest>(rpc::MSG_TYPE::REQ_RPC, onRpcRequest);
//     dispatcher->registerHandler<rpc::TopicRequest>(rpc::MSG_TYPE::REQ_TOPIC, onTopicRequest);

//     rpc::BaseServer::ptr server = rpc::ServerFactory::create(8080);
//     server->setMessageCallback(std::bind(&rpc::Dispatcher::onMessage, dispatcher.get(), std::placeholders::_1, std::placeholders::_2));
//     server->start();


//     return 0;
// }

// MuduoServer
// MuduoClient

// int main()
// {
//     BaseServer::ptr bsp = rpc::ServerFactory::create(8080);
    
//     bsp->start();
    
//     return 0;
// }

// int main()
// {
//     rpc::RpcRequest::ptr rrp = rpc::MessageFactory::create<rpc::RpcRequest>();

//     rrp->setMethod("Add");
//     Json::Value params;
//     params["num1"] = 11;
//     params["num2"] = 22;

//     rrp->setParams(params);

//     std::string str;
//     str = rrp->serialize();
//     std::cout << str << std::endl;

//     rpc::BaseMessage::ptr bmp = rpc::MessageFactory::create(rpc::MSG_TYPE::REQ_RPC);
//     bmp->unserialize(str);
//     bool ret = bmp->check();
//     if (ret == false)
//         return -1;
    
//     rpc::RpcRequest::ptr rrp2 = std::dynamic_pointer_cast<RpcRequest>(bmp);
//     ret = rrp2->check();
//     if (ret == false)
//         return -1;
    
//     std::cout << rrp2->method() << std::endl;
//     std::cout << rrp2->params()["num1"] << std::endl;
//     std::cout << rrp2->params()["num2"] << std::endl;

//     return 0;
// }


// int main()
// {
//     //TopicRequest::ptr ptr = rpc::MessageFactroy::create<TopicRequest>();
//     BaseMessage::ptr bmp = rpc::MessageFactroy::create(MSG_TYPE::REQ_TOPIC);
//     TopicRequest::ptr ptr = std::dynamic_pointer_cast<TopicRequest>(bmp);

//     ptr->setTopicTheme("Happy Friday");
//     ptr->setTopicOption(TOPIC_OP_TYPE::TOPIC_PUBLISH);
//     ptr->setTopicMsg("happy");
    
//     // ptr->setMethod("Add");
//     // Json::Value params;
//     // params["num1"] = 11;
//     // params["num2"] = 22;
//     // ptr->setParams(params);

//     std::string body = ptr->serialize();

//     std::cout << body << std::endl;

//     return 0;
// }

// int main()
// {
//     // rpc::ServiceResponse::ptr srp = rpc::Factroy::create<rpc::ServiceResponse>();
//     auto srp = rpc::Factroy::create<rpc::ServiceRequest>();
//     // auto srp = Factroy::create(MSG_TYPE::REQ_SERVICE);

//     // srp->setRcode(200);
//     srp->setId(UUID::uuid());
//     Address addr("127.0.0.1", 8080);
//     srp->setHost(addr);
//     srp->setOption(SERVICE_OP_TYPE::SERVICE_ONLINE);
//     srp->setMethod("Add");

//     // srp->setTopicMsg("friday");
//     // srp->setTopicTheme("friday");
//     // srp->setTopicOption(TOPIC_OP_TYPE::TOPIC_PUBLISH);

//     // srp->setMethod("Add");
//     // Json::Value params;
//     // params["nums1"] = 11;
//     // params["nums2"] = 22;

//     // srp->setParams(params);

//     // srp->setResult("...");
//     // srp->setHosts({{"127.0.0.1", 8080}});
//     // srp->setMethod("Add");
//     // srp->setOption(SERVICE_OP_TYPE::SERVICE_ONLINE);
//     int ret = srp->check();
//     std::cout << ret << std::endl;

//     return 0;
// }





// int main()
// {
//     // printf("hello\n");
//     // LOG(DEFAULT, "hello, %d+%d=%d", 10, 20, 10 + 20);
//     // ELOG("hello world, %d, %s", 11, "test LOG");

//     // for (int i = 0; i < 20; i++)
//     // {
//     //     std::cout << jsonrpc::UUID::uuid() << std::endl;
//     // }

//     Json::Value student;
//     student["姓名"] = "吴小狗";
//     student["性别"] = "男";
//     student["年龄"] = 21;

//     std::string stu;
//     rpc::JSON::Serialize(student, stu);

//     // std::cout << stu << std::endl;

//     Json::Value val;
//     rpc::JSON::Unserialize(val, stu);
//     std::cout << "姓名" << " : " << val["姓名"].asCString() << std::endl;
//     std::cout << "性别" << " : " << val["性别"].asCString() << std::endl;
//     std::cout << "年龄" << " : " << val["年龄"].asInt() << std::endl;

//     // 不是这么用的！！
//     // std::cout << val[0] << " : " << val[0].asCString() << std::endl;
//     // std::cout << val[1] << " : " << val[1].asCString() << std::endl;
//     // std::cout << val[2] << " : " << val[2].asInt() << std::endl;
//     return 0;
// }